home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / internet / other / ka9q / nhclb120.zoo / icmpcmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-18  |  4.6 KB  |  231 lines

  1. /* ICMP-related user commands */
  2. #include <stdio.h>
  3. #include "global.h"
  4. #include "icmp.h"
  5. #include "mbuf.h"
  6. #include "netuser.h"
  7. #include "internet.h"
  8. #include "timer.h"
  9. #include "ping.h"
  10. static int pingem();
  11. static int16 hash_ping();
  12. static struct ping *add_ping();
  13. static int del_ping();
  14.  
  15.  
  16. int
  17. doicmpstat()
  18. {
  19.     extern struct icmp_errors icmp_errors;
  20.     extern struct icmp_stats icmp_stats;
  21.     extern char *icmptypes[];
  22.     register int i;
  23.  
  24.     printf("ICMP: chksum err %u no space %u icmp %u bdcsts %u\n",
  25.      icmp_errors.checksum,icmp_errors.nospace,icmp_errors.noloop,
  26.      icmp_errors.bdcsts);
  27.     printf("type  rcvd  sent\n");
  28.     for(i=0;i<ICMP_TYPES;i++){
  29.         if(icmp_stats.input[i] == 0 && icmp_stats.output[i] == 0)
  30.             continue;
  31.         printf("%-6u%-6u%-6u",i,icmp_stats.input[i],
  32.             icmp_stats.output[i]);
  33.         if(icmptypes[i] != NULLCHAR)
  34.             printf("  %s",icmptypes[i]);
  35.         printf("\n");
  36.     }
  37.     return 0;
  38. }
  39.  
  40. /* Hash table list heads */
  41. struct ping *ping[PMOD];
  42.  
  43. /* Counter for generating seq numbers */
  44. static int16 iclk;
  45.  
  46. /* Increment counter -- called by low level clock tick */
  47. icmpclk()
  48. {
  49.     iclk++;
  50. }
  51.  
  52. /* Send ICMP Echo Request packets */
  53. doping(argc,argv)
  54. int argc;
  55. char *argv[];
  56. {
  57.     int32 dest;
  58.     struct ping *add_ping(),*pp1;
  59.     register struct ping *pp;
  60.     void ptimeout();
  61.     int16 hval,hash_ping();
  62.     int i;
  63.     char *inet_ntoa();
  64.  
  65.     if(argc < 2){
  66.         printf("Host                Sent    Rcvd   %%   Avg RTT  Interval\n");
  67.         for(i=0;i<PMOD;i++){
  68.             for(pp = ping[i];pp != NULLPING;pp = pp->next){
  69.                 printf("%-16s",inet_ntoa(pp->remote));
  70.                 printf("%8lu%8lu",pp->count,pp->echoes);
  71.                 printf("%4lu%10lu%10lu\n",
  72.                  (long)pp->echoes * 100 / pp->count,
  73.                  pp->echoes != 0 ? 
  74.                  (long)pp->ttotal * MSPTICK / pp->echoes : 0,
  75.                  ((long)pp->timer.start * MSPTICK + 500) / 1000);
  76.             }
  77.         }
  78.         return 0;
  79.     }
  80.     if(strcmp(argv[1],"clear") == 0){
  81.         for(i=0;i<PMOD;i++){
  82.             for(pp = ping[i];pp != NULLPING;pp = pp1){
  83.                 pp1 = pp->next;
  84.                 del_ping(pp);
  85.             }
  86.         }
  87.         return 0;
  88.     }
  89.     if((dest = resolve(argv[1])) == 0){
  90.         printf("Host %s unknown\n",argv[1]);
  91.         return 1;
  92.     }
  93.     /* See if dest is already in table */
  94.     hval = hash_ping(dest);
  95.     for(pp = ping[hval]; pp != NULLPING; pp = pp->next){
  96.         if(pp->remote == dest){
  97.             break;
  98.         }
  99.     }
  100.     if(argc > 2){
  101.         /* Inter-ping time is specified; set up timer structure */
  102.         if(pp == NULLPING)
  103.             pp = add_ping(dest);
  104.         pp->timer.start = atoi(argv[2]) * (1000.0 / MSPTICK);
  105.         pp->timer.func = ptimeout;
  106.         pp->timer.arg = (char *)pp;
  107.         pp->remote = dest;
  108.         start_timer(&pp->timer);
  109.         pp->count++;
  110.         (void)pingem(dest,iclk,REPEAT);
  111.     } else
  112.         (void)pingem(dest,iclk,ONESHOT);
  113.  
  114.     return 0;
  115. }
  116.  
  117. /* Called by ping timeout */
  118. void
  119. ptimeout(p)
  120. char *p;
  121. {
  122.     register struct ping *pp;
  123.  
  124.     /* Send another ping */
  125.     pp = (struct ping *)p;
  126.     pp->count++;
  127.     (void)pingem(pp->remote,iclk,REPEAT);
  128.     start_timer(&pp->timer);
  129. }
  130. /* Send ICMP Echo Request packet */
  131. static
  132. pingem(dest,seq,id)
  133. int32 dest;
  134. int16 seq;
  135. int16 id;
  136. {
  137.     struct mbuf *bp,*htonicmp();
  138.     struct icmp icmp;
  139.     extern struct icmp_stats icmp_stats;
  140.  
  141.     icmp_stats.output[ECHO]++;
  142.     icmp.type = ECHO;
  143.     icmp.code = 0;
  144.     icmp.args.echo.seq = seq;
  145.     icmp.args.echo.id = id;
  146.     if((bp = htonicmp(&icmp,NULLBUF)) == NULLBUF)
  147.         return 0;
  148.     return ip_send(ip_addr,dest,ICMP_PTCL,0,0,bp,len_mbuf(bp),0,0);
  149. }
  150.  
  151. /* Called with incoming Echo Reply packet */
  152. /*ARGSUSED*/
  153. int
  154. echo_proc(source,dest,icmp)
  155. int32 source,dest;
  156. struct icmp *icmp;
  157. {
  158.     register struct ping *pp;
  159.     int16 hval,hash_ping();
  160.     int16 rtt;
  161.     char *inet_ntoa();
  162.  
  163.     rtt = iclk - icmp->args.echo.seq;
  164.     hval = hash_ping(source);
  165.     for(pp = ping[hval]; pp != NULLPING; pp = pp->next)
  166.         if(pp->remote == source)
  167.             break;
  168.     if(pp == NULLPING || icmp->args.echo.id != 1){
  169.         printf("%s: echo reply id %u seq %u, %lu ms\n",
  170.          inet_ntoa(source),
  171.          icmp->args.echo.id,icmp->args.echo.seq,
  172.          (long)rtt * MSPTICK);
  173.          fflush(stdout);
  174.     } else {
  175.         /* Repeated poll, just keep stats */
  176.         pp->ttotal += rtt;
  177.         pp->echoes++;
  178.     }
  179. }
  180. static
  181. int16
  182. hash_ping(dest)
  183. int32 dest;
  184. {
  185.     int16 hval;
  186.  
  187.     hval = (hiword(dest) ^ loword(dest)) % PMOD;
  188.     return hval;
  189. }
  190. /* Add entry to ping table */
  191. static
  192. struct ping *
  193. add_ping(dest)
  194. int32 dest;
  195. {
  196.     struct ping *pp;
  197.     int16 hval,hash_ping();
  198.  
  199.     pp = (struct ping *)calloc(1,sizeof(struct ping));
  200.     if(pp == NULLPING)
  201.         return NULLPING;
  202.  
  203.     hval = hash_ping(dest);
  204.     pp->prev = NULLPING;
  205.     pp->next = ping[hval];
  206.     if(pp->next != NULLPING)
  207.         pp->next->prev = pp;
  208.     ping[hval] = pp;
  209.     return pp;
  210. }
  211. /* Delete entry from ping table */
  212. static
  213. del_ping(pp)
  214. struct ping *pp;
  215. {
  216.     int16 hval,hash_ping();
  217.  
  218.     stop_timer(&pp->timer);
  219.  
  220.     if(pp->next != NULLPING)
  221.         pp->next->prev = pp->prev;
  222.     if(pp->prev != NULLPING) {
  223.         pp->prev->next = pp->next;
  224.     } else {
  225.         hval = hash_ping(pp->remote);
  226.         ping[hval] = pp->next;
  227.     }
  228.     free((char *)pp);    
  229. }
  230.  
  231.